package com.baidu.encrypt.handler;

import com.baidu.encrypt.common.utils.SM4Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.Properties;

@Slf4j
@Intercepts({
    @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class DecryptResultInterceptor implements Interceptor {

    @Autowired
    private SM4Util sm4Util;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();

        if (result instanceof List) {
            for (Object obj : (List<?>) result) {
                decryptObject(obj);
            }
        } else {
            decryptObject(result);
        }
        return result;
    }

    private void decryptObject(Object obj) {
        if (obj == null) {
            return;
        }

        try {
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                String fieldName = field.getName();
                if ("id".equalsIgnoreCase(fieldName) || "sm3".equalsIgnoreCase(fieldName)) {
                    continue;
                }
                Object value = field.get(obj);
                if (value != null) {
                    String decrypted = sm4Util.decrypt(value.toString());
                    field.set(obj, decrypted);
                }
            }
        } catch (Exception e) {
            log.error("解密失败", e);
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {}
}
